package cn.zifangsky.jvm.part1.structure;

/**
 * 局部变量对垃圾回收的影响
 *
 * @author zifangsky
 * @date 2020/7/1
 * @since 1.0.0
 */
public class LocalVarGC {

    /**
     * JVM参数：
     * -Xms40M -Xmx40M -Xmn24M -XX:SurvivorRatio=2 -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc
     * -Xms40M -Xmx40M -Xmn24M -XX:SurvivorRatio=2 -XX:+UseSerialGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC
     */
    public static void main(String[] args) {
        LocalVarGC instance = new LocalVarGC();
        instance.localVarGc4();
    }

    /**
     * 由于byte数组仍然被变量a引用，因此无法回收这块空间
     */
    public void localVarGc1() {
        byte[] a = new byte[5 * 1024 * 1024];
        System.gc();
    }

    /**
     * 在垃圾回收前，先将变量a置为null，使byte数组失去强引用，
     * 故垃圾回收器可以顺利回收byte数组所在的这块空间
     */
    public void localVarGc2() {
        byte[] a = new byte[5 * 1024 * 1024];
        a = null;
        System.gc();
    }

    /**
     * 在垃圾回收前，先使局部变量a失效，虽然变量a已经离开作用域，但是变量a仍然存在局部变量表中，
     * 同时也指向这块byte数组，故这块byte数组无法被回收
     */
    public void localVarGc3() {
        {
            byte[] a = new byte[5 * 1024 * 1024];
        }
        System.gc();
    }

    /**
     * 在垃圾回收前，不仅局部变量a已经失效，同时还让局部变量b占用其槽位，
     * 故垃圾回收器可以顺利回收byte数组所在的这块空间
     */
    public void localVarGc4() {
        {
            byte[] a = new byte[5 * 1024 * 1024];
        }
        int b = 10;
        System.gc();
    }

    /**
     * 虽然在 localVarGc1() 中并没有释放byte数组，但是在 localVarGc1() 调用结束后它的栈帧被销毁，
     * 自然也就包含栈帧中的所有局部变量，而这导致了byte数组失去强引用，
     * 故垃圾回收器可以顺利回收byte数组所在的这块空间
     */
    public void localVarGc5() {
        localVarGc1();
        System.gc();
    }

}
